package com.hhf.ftp.service.impl;

import com.hhf.ftp.service.FtpService;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.sftp.RemoteResourceInfo;
import net.schmizz.sshj.sftp.SFTPClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
import net.schmizz.sshj.xfer.FileSystemFile;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.List;

/**
 * 各方法参数仅支持绝对路径
 */
@Service("sftp")
public class SftpServiceImpl implements FtpService {
    private final static String HOME_DIR = System.getProperty("user.home");
    private SSHClient client;
    private Session session;
    private SFTPClient sftpClient;

    @Override
    public String connection(String username, String password, String ip, Integer port) throws IOException {
        if(port == null) {
            port = 22;
        }
        getClient(username, password, ip, port);
        return "SFTP connection success!";
    }

    @Override
    public void scpPut(String uploadFile, String directory, String encode) throws IOException {
        client.newSCPFileTransfer().upload(new FileSystemFile(uploadFile), directory);
    }

    @Override
    public void scpGet(String filename, String localPath, String encode) throws IOException {
        if(!StringUtils.hasText(localPath)) {
            localPath = HOME_DIR;
        }
        client.newSCPFileTransfer().download(filename, new FileSystemFile(localPath));
    }

    @Override
    public void put(String uploadFile, String directory, String encode) throws IOException {
        sftpClient.put(new FileSystemFile(uploadFile), directory);
    }

    @Override
    public void get(String filename, String localPath, String encode) throws IOException {
        if(!StringUtils.hasText(localPath)) {
            localPath = HOME_DIR;
        }
        sftpClient.get(filename, new FileSystemFile(localPath));
    }

    @Override
    public void rm(String filePath, String encode) throws IOException {
        if(filePath.endsWith("/")) {
            sftpClient.rmdir(filePath);
        }
        sftpClient.rm(filePath);
    }

    /**
     * sftp下没有该命令，使用SSH命令执行
     * @param directory
     * @throws IOException
     */
    @Override
    public void cd(String directory, String encode) throws IOException {
        bash("cd " + directory);
    }

    /**
     * SFTP下没有该命令，使用SSH命令执行
     * @throws IOException
     */
    @Override
    public void cdup() throws IOException {
        bash("cd ../");
    }

    @Override
    public void mkdir(String directory, String encode) throws IOException {
        sftpClient.mkdirs(directory);
    }

    @Override
    public String ls(String dir, String encode) throws IOException {
        if(!StringUtils.hasText(dir)) {
            dir = bash("pwd").replace("\n","");
        }
        List<RemoteResourceInfo> ls = sftpClient.ls(dir);
        String reduce = ls.stream().map(var->var.toString()+"\n").reduce("", String::concat);
        return reduce;
    }

    /**
     * SFTP下没有该命令，使用SSH命令执行
     * @param encode
     * @return
     * @throws IOException
     */
    @Override
    public String pwd(String encode) throws IOException {
        return bash("pwd");
    }

    @Override
    public void mv(String from, String to, String encode) throws IOException {
        sftpClient.rename(from, to);
    }

    @Override
    public String bash(String cmdLine) throws IOException {
        Session.Command cmd = exec(cmdLine);
        return IOUtils.readFully(cmd.getInputStream()).toString();
    }

    @Override
    public String close() throws IOException {
        if (session != null) {
            session.close();
        }
        if(sftpClient != null) {
            sftpClient.close();
        }
        if (client != null) {
            client.disconnect();
        }
        return "Bye!";
    }

    private Session.Command exec(String cmdLine) throws IOException {
        session = client.startSession();
        Session.Command exec = session.exec(cmdLine);
        return exec;
    }
    private void getClient(String username, String password, String remoteHost, Integer port) throws IOException {
        SSHClient client = new SSHClient();
//        client.loadKnownHosts();
//        client.authPublickey(System.getProperty("user.name"));
        client.addHostKeyVerifier(new PromiscuousVerifier());
        client.connect(remoteHost, port);
        client.authPassword(username, password);
        this.client = client;
        SFTPClient sftpClient = client.newSFTPClient();
        this.sftpClient = sftpClient;
    }

}
